package core

import (
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/studio-b12/gowebdav"
)

type WebDAVClient struct {
	client *gowebdav.Client
}

func NewWebDAVClient(hostname, username, password, protocol string, port int, path string) *WebDAVClient {
	url := fmt.Sprintf("%s://%s:%d%s", protocol, hostname, port, path)
	client := gowebdav.NewClient(url, username, password)
	return &WebDAVClient{client: client}
}

func (c *WebDAVClient) DownloadFile(remotePath, localPath string) {
	// Open local file for appending, create if not exists
	localFile, err := os.OpenFile(localPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Failed to open local file: %v", err)
	}
	defer localFile.Close()

	// Get current file size to resume download from the correct offset
	localFileInfo, err := localFile.Stat()
	if err != nil {
		log.Fatalf("Failed to get local file info: %v", err)
	}
	offset := localFileInfo.Size()

	const chunkSize int64 = 16 * 1024 * 1024 // 16 MB

	last_offset := int64(0)

	for {
		start := time.Now()
		fmt.Printf("offset: %v\n", offset)

		// Read a chunk of the remote file
		remoteFile, err := c.client.ReadStreamRange(remotePath, offset, chunkSize)
		if err != nil {
			log.Fatalf("Failed to read remote file: %v", err)
		}

		fmt.Printf("remoteFile: %v\n", remoteFile)

		// Copy the chunk to the local file
		n, err := io.Copy(localFile, remoteFile)
		if err != nil {
			log.Fatalf("Failed to copy data: %v", err)
		}

		fmt.Printf("n: %v\n", n)

		remoteFile.Close()

		if n < chunkSize {
			break // Reached the end of the file
		}

		offset += n

		if offset-last_offset >= chunkSize {
			last_offset = offset
			fmt.Printf("offset: %v\n", offset)
		}

		duration := time.Since(start)
		fmt.Printf("Iteration took %v\n", duration)
	}

	fmt.Printf("Downloaded %s to %s\n", remotePath, localPath)
}

func (c *WebDAVClient) DeleteFile(remotePath string) {
	err := c.client.Remove(remotePath)
	if err != nil {
		log.Fatalf("Failed to delete file: %v", err)
	}
	fmt.Printf("Deleted %s\n", remotePath)
}

func (c *WebDAVClient) CreateDirectory(remotePath string) {
	err := c.client.Mkdir(remotePath, 075)
	if err != nil {
		log.Fatalf("Failed to create directory: %v", err)
	}
	fmt.Printf("Created directory %s\n", remotePath)
}

func (c *WebDAVClient) DeleteDirectory(remotePath string) {
	err := c.client.Remove(remotePath)
	if err != nil {
		log.Fatalf("Failed to delete directory: %v", err)
	}
	fmt.Printf("Deleted directory %s\n", remotePath)
}

func (c *WebDAVClient) ListDirectory(remotePath string) {
	files, err := c.client.ReadDir(remotePath)
	if err != nil {
		log.Fatalf("Failed to list directory: %v", err)
	}
	fmt.Printf("List of files in %s:\n", remotePath)
	for _, f := range files {
		fmt.Println(f.Name())
	}
}

func DavDownload() {
	hostname := "81.70.84.40"
	username := "caoyiming233@126.com"
	password := "xyh9dTW3rWpy7smj8m0qHeBPzM09spFu"

	client := NewWebDAVClient(
		hostname,
		username,
		password,
		"http",
		5212,
		"/dav",
	)

	// 上传文件
	// client.UploadFile("local_file.txt", "/remote_path/remote_file.txt")

	// 下载文件
	// client.DownloadFile("/remote_path/remote_file.txt", "local_file.txt")

	// 删除文件
	// client.DeleteFile("/remote_path/remote_file.txt")

	// 创建目录
	// client.CreateDirectory("/remote_path/new_directory")

	// 删除目录
	// client.DeleteDirectory("/remote_path/new_directory")

	// 列出目录内容
	// client.ListDirectory("/weights")

	client.DownloadFile("/weights/model-00001-of-00003.safetensors", "model-00001-of-00003.safetensors")
}
